
package com.scs.application.modules.upms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.ParamKeys;
import com.scs.application.core.global.GlobalParamService;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.*;
import com.scs.application.modules.upms.dto.LoginDTO;
import com.scs.application.modules.upms.dto.UsernameAndPasswordLoginDTO;
import com.scs.application.modules.upms.entity.OnlineUser;
import com.scs.application.modules.upms.mapper.OnlineUserMapper;
import com.scs.application.modules.upms.request.OnlineUserQueryRequest;
import com.scs.application.modules.upms.service.OnlineUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
* 在线用户 service 实现
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class OnlineUserServiceImpl extends BaseServiceImpl<OnlineUserMapper, OnlineUser> implements OnlineUserService {

    @Autowired
    private GlobalParamService globalParamService;
    @Override
    public List<OnlineUser> list(OnlineUserQueryRequest request) {
        List<OnlineUser> list = this.list(Wrappers.<OnlineUser>query()
                .eq(StringUtils.isNotBlank(request.getLoginKey()), "login_key", request.getLoginKey())
                .between(request.getBeginLoginTime() != null && request.getEndLoginTime() != null, "login_time", request.getBeginLoginTime(), request.getEndLoginTime())
                .eq(StringUtils.isNotBlank(request.getLoginIp()), "login_ip", request.getLoginIp())
            .orderByDesc("login_time")
        );
        return list;
    }

    @Override
    public IPage<OnlineUser> page(OnlineUserQueryRequest request) {
        IPage page = this.page(request.getPage(), Wrappers.<OnlineUser>query()
                .eq(StringUtils.isNotBlank(request.getLoginKey()), "login_key", request.getLoginKey())
                .between(request.getBeginLoginTime() != null && request.getEndLoginTime() != null, "login_time", request.getBeginLoginTime(), request.getEndLoginTime())
                .eq(StringUtils.isNotBlank(request.getLoginIp()), "login_ip", request.getLoginIp())
            .orderByDesc("login_time")
        );
        return page;
    }

    @Override
    public OnlineUser applyToken(String loginKey, LoginDTO loginDTO) {
        // 超时时间，默认两小时
        long timeout = 72 * 60 * 60 * 1000;

        String requestIp = WebUtils.getRequestIp();
        if (IPUtils.isLocalAddr(requestIp)) {
            timeout = 72 * 60 * 60 * 1000;
        }

        String token = Md5Utils.md5(loginKey + UUID.randomUUID().toString());

        //当前时间
        Date now = new Date();
        //过期时间
        Date expireTime = new Date(now.getTime() + timeout);

//        String deviceType = "0";

        // 是否支持同一设备类型多处登录
        boolean allowMultipleLogin = globalParamService.getBoolean(ParamKeys.ALLOW_MULTIPLE_LOGIN, false);
        if (!allowMultipleLogin) {
            // 如果不支持，删除之前所有的token，重新创建
            List<OnlineUser> onlineUsers = baseMapper.selectList(
                    new QueryWrapper<OnlineUser>().eq("login_key", loginKey));
            for (OnlineUser onlineUser : onlineUsers) {
                // 删除SHIRO缓存
                CacheUtils.remove(CacheUtils.AUTHENTICATION_CACHE, onlineUser.getToken());
            }

            baseMapper.delete(new QueryWrapper<OnlineUser>().eq("login_key", loginKey));
        } else {
            // 删除已经过期的token，避免数据堆积
            baseMapper.delete(new QueryWrapper<OnlineUser>().eq("login_key", loginKey).lt("expire_time", new Date()));
        }

        OnlineUser userToken = new OnlineUser();
        userToken.setToken(token)
                .setLoginIp(requestIp)
                .setJti(token)
                .setLoginTime(new Date())
                .setLoginKey(loginKey)
                .setExpireTime(expireTime);
        if (StringUtils.isNotBlank(((UsernameAndPasswordLoginDTO) loginDTO).getOpenId())) {
            userToken.setOpenId(((UsernameAndPasswordLoginDTO) loginDTO).getOpenId());
        }
        this.save(userToken);
        return userToken;
    }

    @Override
    public OnlineUser findByToken(String token) {
        return this.getOne(
                Wrappers.<OnlineUser>query()
                        .eq("token", token)
                        .last("limit 1")
        );
    }
}
